using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;
using Workflows.Components.ETL.Properties;

namespace Workflows.Components.ETL
{ 
    [Serializable]
    public class SaveToDBComponent:WorkflowComponentBase
    {
        #region props

        private SaveToDbInstruction _Instruction;
        private SaveToDBOutput _Output;


        public TableUpdateAction UpdateAction
        {
            get { return this._Instruction.UpdateAction; }
            set { this._Instruction.UpdateAction = value; }
        }

        public TableDataFeedType TableFeedType
        {
            get { return this._Instruction.TableFeedType; }
            set { this._Instruction.TableFeedType = value; }
        }

        public string SrcObjectTypeName
        {
            get { return this._Instruction.SrcObjectTypeName; }
            set { this._Instruction.SrcObjectTypeName = value; }
        }

        public List<TableColumn> SourceTableColumns
        {
            get { return this._Instruction.SourceTableColumns; }
            set { this._Instruction.SourceTableColumns = value; }
        }

        public bool EnableIdentityInsert
        {
            get
            {
                return this._Instruction.EnableIdentityInsert;
            }
            set
            {
                this._Instruction.EnableIdentityInsert = value;
            }
        }

        public Dictionary<string,string> FieldMappings
        {
            get { return this._Instruction.FieldMappings; }
            set { this._Instruction.FieldMappings = value; }
        }

        public string PkField
        {
            get { return this._Instruction.PkField; }
            set { this._Instruction.PkField = value; }
        }

        public string ConnectionString
        {
            get { return this._Instruction.ConnectionString; }
            set { this._Instruction.ConnectionString = value; }
        }

        public string TableName
        {
            get { return this._Instruction.TableName; }
            set { this._Instruction.TableName = value; }
        }

        public override InstructionBase Instruction
        {
            get { return this._Instruction; }
            set { this._Instruction = (SaveToDbInstruction) value; }
        }

        public override ResultBase Output
        {
            get { return this._Output; }
            set { this._Output = (SaveToDBOutput) value; }
        }

        #endregion

        public SaveToDBComponent():base()
        {
            this.ComponentActivityType = WorkflowActivityType.SimpleActivity;
            this.ComponentCategory = WorkflowComponentCategory.ETL.ToString();
            this.Description = "Save data from memory to database";
            this.ComponentIcon = Resources.database;
            this.ComponentImage = Resources.surgepr2_JPG;
            this.ComponentName = "Save to DB";

            this._Instruction =
                new SaveToDbInstruction(this.ComponentID, Guid.Empty,
                    TableUpdateAction.Insert, TableDataFeedType.ObjectListInMemory,
                                        string.Empty, null, string.Empty, string.Empty, string.Empty, false);
            this._Output = new SaveToDBOutput(this.ComponentID, Guid.Empty, 0);
        }
	

        public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
        {
            XmlNode xNode = XmlDataUtil.AddElement(ref xDoc, parentNode, "Component");

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "Type", this.GetType().FullName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ComponentID", this.ComponentID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ComponentName", this.ComponentName);

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "UpdateAction", ((int)this.UpdateAction).ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TableFeedType",((int)this.TableFeedType).ToString());
            
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "PkField", this.PkField);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ConnectionString", this.ConnectionString);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TableName", this.TableName);
            XmlDataUtil.UpdateAttribute(ref xDoc,xNode,"EnableIdentityInsert",this.EnableIdentityInsert.ToString());

            if (this.TableFeedType == TableDataFeedType.ObjectListInMemory)
            {
                XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcObjectTypeName", this.SrcObjectTypeName);
            }
            else
            {
                if (this.SourceTableColumns != null && this.SourceTableColumns.Count > 0)
                {
                    XmlNode srcSchemaNode = XmlDataUtil.AddElement(ref xDoc, xNode, "SourceTableColumns");
                    foreach (TableColumn col in this.SourceTableColumns)
                    {
                        XmlNode tblColNode = XmlDataUtil.AddElement(ref xDoc, srcSchemaNode, "TableColumn");
                        XmlDataUtil.UpdateAttribute(ref xDoc, tblColNode, "ColumnName", col.ColumnName);
                        XmlDataUtil.UpdateAttribute(ref xDoc, tblColNode, "Ordinal", col.Ordinal.ToString());
                        XmlDataUtil.UpdateAttribute(ref xDoc, tblColNode, "DbType", ((int) col.DbType).ToString());
                        XmlDataUtil.UpdateAttribute(ref xDoc, tblColNode, "Size", col.Size.ToString());
                        XmlDataUtil.UpdateAttribute(ref xDoc, tblColNode, "IsPK", col.IsPK.ToString());
                        XmlDataUtil.UpdateAttribute(ref xDoc, tblColNode, "IsIdentity", col.IsIdentity.ToString());
                        XmlDataUtil.UpdateAttribute(ref xDoc, tblColNode, "AllowNull", col.AllowNull.ToString());
                    }
                }
            }

            if(this.FieldMappings !=null && this.FieldMappings.Count>0)
            {
                XmlNode fieldMappingNodes = XmlDataUtil.AddElement(ref xDoc, xNode, "FieldMappings");
                foreach(string srcField in this.FieldMappings.Keys)
                {
                    XmlNode fieldMappingNode = XmlDataUtil.AddElement(ref xDoc, fieldMappingNodes, "FieldMapping");
                    XmlDataUtil.UpdateAttribute(ref xDoc,fieldMappingNode,"SrcField",srcField);
                    XmlDataUtil.UpdateAttribute(ref xDoc,fieldMappingNode,"TargetField",this.FieldMappings[srcField]);
                }
            }
            return xNode;
        }

        public override WorkflowComponentBase Instantiate(XmlNode xNode)
        {
            if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
            {
                SaveToDBComponent saveDB = base.Instantiate(xNode) as SaveToDBComponent;

                saveDB.UpdateAction = (TableUpdateAction) int.Parse(xNode.Attributes.GetNamedItem("UpdateAction").Value);
                saveDB.TableFeedType =(TableDataFeedType) int.Parse(xNode.Attributes.GetNamedItem("TableFeedType").Value);
                if(saveDB.TableFeedType==TableDataFeedType.ObjectListInMemory)
                {
                    saveDB.SrcObjectTypeName = xNode.Attributes.GetNamedItem("SrcObjectTypeName").Value;
                }
                else
                {
                    saveDB.SourceTableColumns=new List<TableColumn>();
                    XmlNodeList colNodes = xNode.SelectNodes("SourceTableColumns/TableColumn");
                    if(colNodes !=null && colNodes.Count>0)
                    {
                        foreach(XmlNode colNode in colNodes)
                        {
                            TableColumn col=new TableColumn();
                            col.ColumnName = colNode.Attributes.GetNamedItem("ColumnName").Value;
                            col.Ordinal = int.Parse(colNode.Attributes.GetNamedItem("Ordinal").Value);
                            col.DbType = (SqlDbType) int.Parse(colNode.Attributes.GetNamedItem("DbType").Value);
                            col.Size = int.Parse(colNode.Attributes.GetNamedItem("Size").Value);
                            col.IsPK = bool.Parse(colNode.Attributes.GetNamedItem("IsPK").Value);
                            col.IsIdentity = bool.Parse(colNode.Attributes.GetNamedItem("IsIdentity").Value);
                            col.AllowNull = bool.Parse(colNode.Attributes.GetNamedItem("AllowNull").Value);
                            saveDB.SourceTableColumns.Add(col);
                        }
                    }
                }
                saveDB.PkField = xNode.Attributes.GetNamedItem("PkField").Value;
                saveDB.ConnectionString = xNode.Attributes.GetNamedItem("ConnectionString").Value;
                saveDB.TableName = xNode.Attributes.GetNamedItem("TableName").Value;
                saveDB.EnableIdentityInsert = bool.Parse(xNode.Attributes.GetNamedItem("EnableIdentityInsert").Value);

                saveDB.FieldMappings = null;
                XmlNodeList fieldMappingNodes = xNode.SelectNodes("FieldMappings/FieldMapping");
                if(fieldMappingNodes !=null && fieldMappingNodes.Count>0)
                {
                    saveDB.FieldMappings=new Dictionary<string, string>();
                    foreach(XmlNode fieldMappingNode in fieldMappingNodes)
                    {
                        string srcField = fieldMappingNode.Attributes.GetNamedItem("SrcField").Value;
                        string tgtField = fieldMappingNode.Attributes.GetNamedItem("TargetField").Value;
                        saveDB.FieldMappings.Add(srcField,tgtField);
                    }
                }

                return saveDB;
            }
            else
                throw new Exception("Unable to instantiate email: invalid type specified in xml node");
        }
    }
}
